package pt.utl.ist.ginger3d;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.Elements;
import nu.xom.Nodes;
import nu.xom.ParsingException;
import nu.xom.ValidityException;
import pt.utl.ist.ginger3d.domain.Block;
import pt.utl.ist.ginger3d.domain.BlockFactory;
import pt.utl.ist.ginger3d.domain.PlaceHolderBlock;
import pt.utl.ist.ginger3d.domain.Template;


/**
 * TODO: use RandomAccessFile
 *	
 */
public class Splitter 
{
    public static void main( String[] args ) throws IOException, ValidityException, ParsingException
    {
    	final BinaryFileReader sample;
        try {
        	sample = new BinaryFileReader("../samples/mpeg4-2.avi");
		} catch (FileNotFoundException e) {
			System.err.println("Sample not found");
			return;
		}
		
		List<Template> templates = new ArrayList<Template>();
    	
		Builder builder = new Builder();
		Document doc = builder.build("etc/avi.gfs");
		
		Nodes nodes = doc.query("/ginger/types");
		Elements typeElems = ((Element) nodes.get(0)).getChildElements("type");
		BlockFactory blockFactory = new BlockFactory();
		for(int i = 0; i < typeElems.size(); i++) {
			blockFactory.addType(typeElems.get(i));
		}
		
		nodes = doc.query("/ginger/templates");
		Elements templateElems = ((Element) nodes.get(0)).getChildElements("template");

		for(int i = 0; i < templateElems.size(); i++) {
			templates.add(blockFactory.newTemplate(templateElems.get(i)));
		}
		nodes = doc.query("/ginger/structure");
		List<Block> structure = blockFactory.getStructure(((Element) nodes.get(0)).getChildElements());
		
		int depth = 0;
		
		printBlocks(structure, new StringBuffer());
		
		System.exit(1);
		
		System.out.println(sample.readString());
		System.out.println(sample.readInt());
		System.out.println(sample.readString());
		System.out.println(sample.readString());
		System.out.println(sample.readInt());
		System.out.println(sample.readString());
		System.out.println(sample.readString());
		System.out.println(sample.readInt()); // size
		System.out.println(sample.readInt()); 
		System.out.println(sample.readInt());
		System.out.println(sample.readInt()); 
		System.out.println(Integer.toBinaryString(sample.readInt()));//flags
		System.out.println(sample.readInt());
		System.out.println(sample.readInt());
		System.out.println(sample.readInt());
		System.out.println(sample.readInt());
		System.out.println(sample.readInt());
		System.out.println(sample.readInt());
		System.out.println(sample.readInt());
		System.out.println(sample.readInt());
		System.out.println(sample.readInt());
		System.out.println(sample.readInt());
		System.out.println(sample.readString());
		System.out.println(sample.readInt());
		System.out.println(sample.readString());
		System.out.println(sample.readString());
		System.out.println(sample.readInt());
		System.out.println(sample.readString());
		System.out.println(sample.readString());
		System.out.println(Integer.toBinaryString(sample.readInt())); //flags
		System.out.println(sample.readInt()); //reserved
		System.out.println(sample.readInt()); //initial
		System.out.println(sample.readInt()); //scale
		System.out.println(sample.readInt()); //rate
		System.out.println(sample.readInt()); //start
		System.out.println(sample.readInt()); //length
		System.out.println(sample.readInt()); // suggestedbuffersize
		System.out.println(sample.readInt()); // quality
		System.out.println("vids sample size: "+sample.readInt()); // sample size
		System.out.println(sample.readInt()); // junk
		System.out.println(sample.readInt()); // junk
		
		System.out.println(sample.readString()); // chunk name strf
		System.out.println("chunk-size: " + sample.readInt()); // chunk size
		System.out.println(sample.readInt()); // biSize
		System.out.println(sample.readInt()); // biWidth
		System.out.println(sample.readInt()); // biHeight
		System.out.println(sample.readShort()); // biPlanes
		System.out.println(sample.readShort()); // biBitCount
		System.out.println(sample.readInt()); // biCompression
		System.out.println(sample.readInt()); // biSizeImage
		System.out.println(sample.readInt()); // biXPelsPerMeter
		System.out.println(sample.readInt()); // biYPelsPerMeter
		System.out.println(sample.readInt()); // biClrUsed
		System.out.println(sample.readInt()); // biClrImportant
		System.out.println(sample.readString()); // JUNK
		int junkSize = sample.readInt();
		sample.addOffset((long)junkSize);
		System.out.println(sample.readString());
		System.out.println(sample.readInt());
		System.out.println(sample.readString());
		System.out.println(sample.readString());
		System.out.println(sample.readInt());
		System.out.println(sample.readString()); //auds
		System.out.println(sample.readInt());
		System.out.println(Integer.toBinaryString(sample.readInt())); //flags
		System.out.println(sample.readInt()); //reserved
		System.out.println(sample.readInt()); //initial
		System.out.println(sample.readInt()); //scale
		System.out.println(sample.readInt()); //rate
		System.out.println(sample.readInt()); //start
		System.out.println(sample.readInt()); //length
		System.out.println(sample.readInt()); // suggestedbuffersize
		System.out.println(sample.readInt()); // quality
		System.out.println("auds sample size: " + sample.readInt()); // sample size
		System.out.println(sample.readInt()); // junk
		System.out.println(sample.readInt()); // junk
		System.out.println(sample.readString()); // strf
		System.out.println(sample.readInt()); // size
		System.out.println(sample.readShort()); // wFormatTag
		System.out.println(sample.readShort()); // nChannels
		System.out.println(sample.readInt()); // nSamplesPerSec
		System.out.println(sample.readInt()); // nAvgBytesPerSec
		System.out.println(sample.readShort()); // nBlockAlign
		System.out.println(sample.readShort()); // wBitsPerSample
		System.out.println(sample.readShort()); // cbSize
		System.out.println(sample.readShort()); // stuff
		System.out.println(sample.readShort()); // stuff
		System.out.println(sample.readShort()); // stuff
		System.out.println(sample.readShort()); // stuff
		System.out.println(sample.readShort()); // stuff
		System.out.println(sample.readShort()); // stuff
		System.out.println(sample.readString());
		junkSize = sample.readInt();
		sample.addOffset((long)junkSize);
		System.out.println(sample.readString());
		System.out.println(sample.readInt());
		System.out.println(sample.readString());
		System.out.println(sample.readString());
		junkSize = sample.readInt();
		sample.addOffset((long)junkSize);
		System.out.println(sample.readString());
		junkSize = sample.readInt();
		sample.addOffset((long)junkSize);
		System.out.println(sample.readString());
		int dataSize = sample.readInt();
		System.out.println("data-size: " + dataSize);
		long moviOffset = sample.getOffset();
		sample.addOffset((long)dataSize);
		System.out.println(sample.readString());
		int idx1Size = sample.readInt();
		int flags;
		int j = 0;
		int kf = 0;
		for(int i=0; i<idx1Size/16; i++) {
			System.out.println("ckid: " + sample.readString());
			flags = sample.readInt();
			if((flags&0x10) != 0) {
				kf++;
			}
			System.out.println("flags: " + Integer.toBinaryString(flags) + "; keyframe?: " + ((flags&0x10) != 0));
			int offset = sample.readInt();
			System.out.println("offset: " + offset);
			// seek to data chunk
			long tmp = sample.getOffset();
			sample.setOffset(moviOffset+offset);
			System.out.println(sample.readString());
			
			// return to index chunk
			sample.setOffset(tmp);
			
			System.out.println("length: " + sample.readInt());
			j=i;
		}
		System.out.println(j);
		System.out.println(kf);
		System.out.println(sample.readString());
		junkSize = sample.readInt();
		System.out.println(junkSize);
		for(int i=0; i<junkSize/4; i++) {
			sample.readInt();
		}
		System.out.println(sample.readByte());
		System.out.println(sample.readByte());
		System.out.println(sample.readByte());
    }

	private static void printBlocks(Collection<Block> structure, StringBuffer buffer) {
		for(Block block : structure) {
			System.out.println(buffer.toString() + block);
			if(block instanceof PlaceHolderBlock) {
				buffer.append(' ');
				printBlocks(((PlaceHolderBlock) block).getBlocks(), buffer);
				buffer.deleteCharAt(buffer.length()-1);
			}
		}
	}
	
}
